package lex.title.liquid;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import javax.swing.JRootPane;

import org.lex.awt.GraphicsUtils;

import lex.title.MaximizeRestoreButton;
import lex.title.MenuButton;
import lex.title.WindowButton;
import lex.title.WindowButtonUI;
import lex.title.basic.BasicWindowTitle;
import lex.util.ImageCache;
import lex.util.Utilities;

public class LiquidWindowTitle extends BasicWindowTitle {
	/**
	 * Color for the title in a normal sized internal frame
	 */
	private Color normalTitleColor = Color.white;
	/**
	 * Color for the shadow of the title in a normal sized internal frame
	 */
	private Color shadowColor = new Color(10, 24, 131);
	// ============================
	MaximizeRestoreButton maximizeRestoreButton;
	WindowButton minimizeButton;
	WindowButton closeButton;
	MenuButton menuButton;
	JPopupMenu menu;

	public LiquidWindowTitle(JRootPane root) {
		super(root);
		if (isFrame()) {
			this.add(this.getMinimizeButton());
			this.add(this.getMaximizeRestoreButton());
		}
		this.add(this.getMenuButton());
		this.add(this.getCloseButton());
		setLayout(new LiquidTitleLayout(this));
	}

	protected JButton getCloseButton() {
		if (null == this.closeButton) {
			ImageCache ic = ImageCache.getInstance();
			WindowButtonUI ui = new WindowButtonUI(ic.getLiquidImage("close-normal.png"), ic.getLiquidImage("close-rollover.png"),
					ic.getLiquidImage("close-pressed.png"), ic.getLiquidImage("close-disabled.png"));
			closeButton = new WindowButton(ui);
			closeButton.setAction(this.getCloseAction());
		}
		return this.closeButton;
	}

	protected MaximizeRestoreButton getMaximizeRestoreButton() {
		if (null == this.maximizeRestoreButton) {
			ImageCache ic = ImageCache.getInstance();
			WindowButtonUI maxUI = new WindowButtonUI(ic.getLiquidImage("maximize-normal.png"), ic.getLiquidImage("maximize-rollover.png"),
					ic.getLiquidImage("maximize-pressed.png"), ic.getLiquidImage("maximize-disabled.png"));
			WindowButtonUI restoreUI = new WindowButtonUI(ic.getLiquidImage("restore-normal.png"), ic.getLiquidImage("restore-rollover.png"),
					ic.getLiquidImage("restore-pressed.png"), ic.getLiquidImage("restore-disabled.png"));
			maximizeRestoreButton = new MaximizeRestoreButton(maxUI, restoreUI);
			maximizeRestoreButton.setActions(getMaximizeAction(), getRestoreAction());
		}
		return this.maximizeRestoreButton;
	}

	protected JButton getMinimizeButton() {
		if (null == this.minimizeButton) {
			ImageCache ic = ImageCache.getInstance();
			WindowButtonUI ui = new WindowButtonUI(ic.getLiquidImage("minimize-normal.png"), ic.getLiquidImage("minimize-rollover.png"),
					ic.getLiquidImage("minimize-pressed.png"), ic.getLiquidImage("minimize-disabled.png"));
			minimizeButton = new WindowButton(ui);
			minimizeButton.setAction(this.getMinimizeAction());
		}
		return this.minimizeButton;
	}

	protected JButton getMenuButton() {
		if (null == this.menuButton) {
			menuButton = new MenuButton(this);
			menuButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					JComponent c = LiquidWindowTitle.this;
					getMenu().show(c, 0, c.getHeight());
				}
			});
		}
		return menuButton;
	}

	protected JPopupMenu getMenu() {
		if (null == this.menu) {
			menu = new JPopupMenu();
			if (false == this.isNoneDecoration()) {
				menu = new JPopupMenu();
				menu.add(this.getRestoreAction());
				menu.add(this.getMinimizeAction());
				menu.add(this.getMaximizeAction());
				menu.addSeparator();
				menu.add(this.getCloseAction());
			}
		}
		return menu;
	}

	protected void paintComponent(Graphics g) {
		if (getFrame() != null) {
			setState(getFrame().getExtendedState());
		}
		Window frame = this.getWindow();
		boolean leftToRight = super.isLeftToRight();
		boolean active = true;
		int width = getWidth();
		int height = getHeight();
		Graphics2D g2 = (Graphics2D) g;
		Object oldAntiAliasingValue = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		drawLiquidCaption(g, active, width, height);
		int titleLength = 0;
		int xOffset = leftToRight ? 2 : (width - 2);
		String title = getTitle();
		int xOvalOffset = 8;
		// Add in the oval offset
		xOffset += (leftToRight) ? xOvalOffset : 0;
		if (title != null) {
			Font f = getFont();
			g.setFont(f);
			FontMetrics fm = g.getFontMetrics();
			titleLength = fm.stringWidth(title);
			int titleW = 0;
			Rectangle r = new Rectangle(0, 0, 0, 0);
			if (leftToRight) {
				if (getMinimizeAction().isEnabled()) {
					r = minimizeButton.getBounds();
				} else if (getMaximizeAction().isEnabled()) {
					r = maximizeRestoreButton.getBounds();
				} else if (getCloseAction().isEnabled()) {
					r = closeButton.getBounds();
				}
				if (r.x == 0) {
					r.x = frame.getWidth() - frame.getInsets().right;
				}
				xOffset += menuButton != null ? (menuButton.getX() + menuButton.getWidth() + 2) : 2;
				titleW = r.x - xOffset - xOvalOffset - 2;
			} else {
				if (getMaximizeAction().isEnabled()) {
					r = maximizeRestoreButton.getBounds();
				} else if (getMinimizeAction().isEnabled()) {
					r = minimizeButton.getBounds();
				} else if (getCloseAction().isEnabled()) {
					r = closeButton.getBounds();
				}
				Rectangle menu = new Rectangle(0, 0, 0, 0);
				if (menu.x == 0) {
					menu.x = frame.getWidth() - frame.getInsets().right;
				}
				xOffset = r.x + r.width + 2;
				titleW = menu.x - xOffset;
			}
			int startTitleLength = fm.stringWidth(title);
			title = Utilities.clipStringIfNecessary(fm, title, titleW);
			titleLength = fm.stringWidth(title);
			if (titleLength == startTitleLength) {
				xOffset += (titleW - titleLength) / 2;
			}
			int yOffset = GraphicsUtils.getVerticalPlacement(fm, height);
			int endOffset = 19;
			if (!leftToRight) {
				xOffset -= titleLength;
			}
			if (active) {
				// for an active window
				if (titleLength > 0) {
					GradientPaint grad = new GradientPaint(xOffset + (titleLength / 2), yOffset - 15, new Color(60, 144, 233), xOffset
							+ (titleLength / 2), endOffset, new Color(102, 186, 255));
					g2.setPaint(grad);
					g2.fillRoundRect(xOffset - 8, yOffset - 15, titleLength + 15, endOffset, 18, 18);
					g.setColor(new Color(0, 78, 167));
					g2.drawRoundRect(xOffset - 8, yOffset - 15, titleLength + 15, endOffset, 18, 18);
				}
				g.setColor(shadowColor);// Color.black);
				g.drawString(title, xOffset + 1, yOffset);
				g.setColor(normalTitleColor);
				g.drawString(title, xOffset, yOffset - 1);
				xOffset += (leftToRight ? (titleLength + 2) : (-2));
			} else {
				// for an inactive window
				if (titleLength > 0) {
					GradientPaint grad = new GradientPaint(xOffset + (titleLength / 2), yOffset - 15, new Color(191, 211, 233), xOffset
							+ (titleLength / 2), endOffset, new Color(233, 253, 255));
					g2.setPaint(grad);
					// g2.fillRoundRect(xOffset-8, yOffset-15, titleLength+15,
					// fm.getHeight()+1, 18, 18);
					g2.fillRoundRect(xOffset - 8, yOffset - 15, titleLength + 15, endOffset, 18, 18);
					g.setColor(new Color(125, 145, 167));
					// g2.drawRoundRect(xOffset-8, yOffset-15, titleLength+15,
					// fm.getHeight()+1, 18, 18);
					g2.drawRoundRect(xOffset - 8, yOffset - 15, titleLength + 15, endOffset, 18, 18);
				}
				g.setColor(Color.black);
				g.drawString(title, xOffset, yOffset - 1);
				xOffset += (leftToRight ? (titleLength + 2) : (-2));
			}
		}
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAntiAliasingValue);
	}

	private void drawLiquidCaption(Graphics g, boolean isSelected, int w, int h) {
		Color c = isSelected ? new Color(62, 145, 235) : new Color(175, 214, 255);
		g.setColor(c);
		g.fillRect(0, 0, w, h - 1);
		c = isSelected ? new Color(94, 172, 255) : new Color(226, 240, 255);
		g.setColor(c);
		g.drawLine(0, 0, w, 0);
		c = isSelected ? new Color(60, 141, 228) : new Color(170, 207, 247);
		g.setColor(c);
		g.drawLine(0, 1, w, 1);
		for (int i = 4; i < (h - 1); i += 4) {
			c = isSelected ? new Color(59, 138, 223) : new Color(166, 203, 242);
			g.setColor(c);
			g.drawLine(0, i, w, i);
			c = isSelected ? new Color(60, 141, 228) : new Color(170, 207, 247);
			g.setColor(c);
			g.drawLine(0, i + 1, w, i + 1);
		}
		c = isSelected ? new Color(47, 111, 180) : new Color(135, 164, 196);
		g.setColor(c);
		g.drawLine(0, h - 1, w, h - 1);
	}
}
